//
//  ESLinkedList.m
//  utils
//
//  Created by easy on 11-12-8.
//  Copyright 2011 zeasy@qq.com. All rights reserved.
//

#import "ESLinkedList.h"

@implementation ESLinkedListNode
@synthesize linkedList = _linkedList;
@synthesize previousNode = _previousNode;
@synthesize nextNode = _nextNode;
@synthesize value = _value;

-(id) initWithValue:(id) value {
	self = [super init];
	if (self) {
		if (value != nil) {
			_value = [value retain];
		}else {
			[self release],self = nil;
		}
	}
	return self;
}
+(id) nodeWithValue:(id) value{
	return [[[self alloc] initWithValue:value] autorelease];
}
- (void) dealloc
{
	_linkedList = nil;
	[_value release],_value = nil;
	[_nextNode release],_nextNode = nil;
	_previousNode = nil;
	[super dealloc];
}

-(void) setNextNode:(ESLinkedListNode *) node {
	if (_nextNode != node) {
		[_nextNode release];
		_nextNode = [node retain];
	}
}
-(void) setPreviousNode:(ESLinkedListNode *) node {
	_previousNode = node;
}
@end


@implementation ESLinkedList
@synthesize headNode = _headNode;
@synthesize tailNode = _tailNode;
@synthesize delegate = _delegate;

-(id) initWithHeadNode:(ESLinkedListNode *) headNode tailNode:(ESLinkedListNode *) tailNode{
	self = [super init];
	if (self != nil) {
		if (headNode == nil) {
			_headNode = [[ESLinkedListNode nodeWithValue:@"head"] retain];
		}else {
			_headNode = [headNode retain];
		}
		if (tailNode == nil) {
			_tailNode = [[ESLinkedListNode nodeWithValue:@"tail"] retain];
		}else {
			_tailNode = [tailNode retain];
		}
	}
	return self;
}
-(id) initWithHeadNode:(ESLinkedListNode *) headNode{
	return [self initWithHeadNode:headNode tailNode:nil];
}
-(id) initWithTailNode:(ESLinkedListNode *) tailNode{
	return [self initWithHeadNode:nil tailNode:tailNode];
}
-(id) init{
	return [self initWithHeadNode:nil tailNode:nil];
}
- (void) dealloc
{
	_delegate = nil;
	[_headNode release],_headNode = nil;
	[_tailNode release],_tailNode = nil;
	[super dealloc];
}

-(NSUInteger) count{
	return _count;
}
-(BOOL) addNode:(ESLinkedListNode *) node beforeNode:(ESLinkedListNode *) beforeNode{
	if (node != nil && node->_linkedList == nil 
		&& beforeNode != nil && beforeNode->_linkedList == self
		&& beforeNode != _headNode) {
		node.nextNode = beforeNode;
		node.previousNode = beforeNode.previousNode;
		beforeNode.previousNode.nextNode = node;
		beforeNode.previousNode = node;
		node->_linkedList = self;
		_count++;
		if (self.delegate != nil && [self.delegate respondsToSelector:@selector(linkedList:addedNode:)]) {
			[self.delegate linkedList:self addedNode:node];
		}
		return YES;
	}
	return NO;
}
-(BOOL) addNode:(ESLinkedListNode *) node afterNode:(ESLinkedListNode *) afterNode{
	if (node != nil && node->_linkedList == nil
		&& afterNode != nil && afterNode->_linkedList == self
		&& afterNode != _tailNode) {
		node.previousNode = afterNode;
		node.nextNode = afterNode.nextNode;
		afterNode.nextNode.previousNode = node;
		afterNode.nextNode = node;
		node->_linkedList = self;
		_count++;
		if (self.delegate != nil && [self.delegate respondsToSelector:@selector(linkedList:addedNode:)]) {
			[self.delegate linkedList:self addedNode:node];
		}
		return YES;
	}
	return NO;
}
-(BOOL) addNode:(ESLinkedListNode *)node atIndex:(NSUInteger) index {
	if (node != nil && node->_linkedList == nil && index <= _count) {
		ESLinkedListNode *prev = nil;
		if (index == 0) {
			prev = _headNode;
		}else {
			prev = [self nodeAtIndex:index - 1];
		}
		return [self addNode:node afterNode:prev];
	}
	return NO;
}
-(BOOL) removeNode:(ESLinkedListNode *) node {
	if (node != nil && node->_linkedList == self && node != _headNode && node != _tailNode) {
		ESLinkedListNode *n = [node retain];
		node.previousNode.nextNode = node.nextNode;
		node.nextNode.previousNode = node.previousNode;
		node.previousNode = nil;
		node.nextNode = nil;
		node->_linkedList = nil;
		_count--;
		if (self.delegate != nil && [self.delegate respondsToSelector:@selector(linkedList:removedNode:)]) {
			[self.delegate linkedList:self removedNode:node];
		}
		[n release];
		return YES;
	}
	return NO;
}
-(BOOL) removeNodeAtIndex:(NSUInteger) index{
	return [self removeNode:[self nodeAtIndex:index]];
}
-(BOOL) replaceNode:(ESLinkedListNode *) node withNode:(ESLinkedListNode *) toNode{
	if (node != nil && node->_linkedList == self && toNode != nil && toNode->_linkedList == nil) {
		ESLinkedListNode *n = [node retain];
		node.previousNode.nextNode = toNode;
		toNode.previousNode = node.previousNode;
		node.nextNode.previousNode = toNode;
		toNode.nextNode = node.nextNode;
		node.previousNode = nil;
		node.nextNode = nil;
		if (self.delegate != nil && [self.delegate respondsToSelector:@selector(linkedList:replaceNode:withNode:)]) {
			[self.delegate linkedList:self replaceNode:node withNode:toNode];
		}
		[n release];
		return YES;
	}
	return NO;
}
-(BOOL) replaceNodeAtIndex:(NSUInteger) index withNode:(ESLinkedListNode *) node{
	return [self replaceNode:[self nodeAtIndex:index] withNode:node];
}

-(ESLinkedListNode *) nodeAtIndex:(NSUInteger) index{
	if (index < _count) {
		NSUInteger count = 0;
		ESLinkedListNode *node = _headNode;
		while (count < index && node != nil) {
			if (count == index) {
				return node;
			}else {
				count++;
				node = node.nextNode;
			}
		}
	}
	return nil;
}
-(NSUInteger) indexOfObject:(id) object{
	if (object != nil) {
		ESLinkedListNode *node = _headNode;
		NSUInteger count = 0;
		while (count < _count && node != _tailNode) {
			if ([node.value isEqual:object]) {
				return count;
			}else {
				count ++;
			}

		}
	}
	return NSNotFound;
}
-(NSUInteger) indexOfNode:(ESLinkedListNode *) node{
	if (node != nil && node->_linkedList == self) {
		ESLinkedListNode *n = _headNode;
		NSUInteger count = 0;
		while (count < _count && n != _tailNode) {
			if (n == node ) {
				return count;
			}else {
				count ++;
			}
			
		}
	}
	return NSNotFound;
}
-(BOOL) addFirst:(ESLinkedListNode *) node{
	return [self addNode:node afterNode:_headNode];
}
-(BOOL) addLast:(ESLinkedListNode *) node{
	return [self addNode:node beforeNode:_tailNode];
}
-(BOOL) removeFirst{
	return [self removeNode:_headNode.nextNode];
}
-(BOOL) removeLast{
	return [self removeNode:_tailNode.previousNode];
}
-(BOOL) offerNode:(ESLinkedListNode *) node{
	return [self addNode:node beforeNode:_tailNode];
}
-(ESLinkedListNode *) peekNode{
	return _headNode.nextNode;
}
-(ESLinkedListNode *) pollNode{
	if (_headNode.nextNode != nil) {
		ESLinkedListNode *node = [_headNode.nextNode retain];
		[self removeNode:_headNode.nextNode];
		return [node autorelease];
	}
	return nil;
}

-(NSArray *) allValues{
	NSMutableArray *array = [NSMutableArray arrayWithCapacity:_count];
	if (_count > 0) {
		ESLinkedListNode *node = _headNode.nextNode;
		while (node != _tailNode) {
			[array addObject:node.value];
			node = node.nextNode;
		}
	}
	return array;
}
-(NSArray *) allNodes{
	NSMutableArray *array = [NSMutableArray arrayWithCapacity:_count];
	if (_count > 0) {
		ESLinkedListNode *node = _headNode.nextNode;
		while (node != _tailNode) {
			[array addObject:node];
			node = node.nextNode;
		}
	}
	return array;
}
@end
